<?php

class WebUser implements IApplicationComponent
{
	public $isInitialized = false;
	private $_uid = null;
	private $_oauthToken = null;
	private $_isAuthen = false;
	
	public function getIsInitialized()
	{
		return $this->isInitialized;
	}
	
	public function init()
	{
		if(isset(Yii::app()->session['WebUser:_uid'])) {
			$this->_uid = Yii::app()->session['WebUser:_uid'];
		}
		else {
			$this->logout();
		}
		if(isset($_GET['oauthToken'])) {
			$this->authenticate($_GET['oauthToken']);
		}
		$this->isInitialized = true;
	}
	
	public function getId()
	{
		return $this->_uid;
	}
	
	public function getToken(){
		return $this->_oauthToken;
	}
	
	public function isAuthen()
	{
		return $this->_isAuYii;
	}
	
	public function logout()
	{
		unset(Yii::app()->session['WebUser:_uid']);
		unset(Yii::app()->request->cookies['oauthToken']);
		$this->_uid = null;
		$this->_oauthToken = null;
		$this->_isAuthen = false;
	}
	
	public function login($email, $password, $expire = 0)
	{
		$account = Account::model()->findByAttributes(array('email'=> $email));
		if($account == null) {
			return false;
		}
		if($account->password == Helper::hasPass($password)) {
			$accountToken = AccountToken::model()->findByAttributes(array("uid"=> $account->uid));
			if($accountToken == null) {
				$accountToken = new AccountToken();
				$accountToken->uid = $account->uid;
				$accountToken->token = $this->genToken();
				if($expire != 0) {
					$accountToken->expireTime = time() + (60 * 60 * 24 * 3);
				}
				if(!$accountToken->save()) {
					throw new PlatwoException(9999, "Can't create token");
				}
			}
			Yii::app()->session['WebUser:_uid'] = $this->_uid = $accountToken->uid;
			$this->_oauthToken = $accountToken->token;
			Yii::app()->request->cookies['oauthToken'] = new CHttpCookie('oauthToken', $accountToken->token);
			$this->_isAuthen = true;
			return true;
		}
		return false;
	}
	
	public function authenticate($token)
	{
		if($this->_uid == null) {
			$accountToken = AccountToken::model()->findByAttributes(array('token'=> $token));
			if($accountToken == null) {
				$this->logout();
				return false;
			}
			else {
				if($accountToken->token == $token) {
					Yii::app()->session['WebUser:_uid'] = $this->_uid = $accountToken->uid;
					$this->_oauthToken = $token;
					Yii::app()->request->cookies['oauthToken'] = new CHttpCookie('oauthToken', $token);
					$this->_isAuthen = true;
					return true;
				}
				else {
					$this->logout();
					return false;
				}
			}
		}
		else {
			$accountToken = Account::model()->findByAttributes(array('uid'=> $this->_uid));
			if($accountToken != null && $accountToken == $token) {
				Yii::app()->session['WebUser:_uid'] = $this->_uid = $accountToken->uid;
				$this->_oauthToken = $token;
				Yii::app()->request->cookies['oauthToken'] = new CHttpCookie('oauthToken', $token);
				$this->_isAuthen = true;
				return true;
			}
			else {
				$this->logout();
				return false;
			}
		}
	}
	
	private function genToken($len = 32, $md5 = true) {
        # Seed random number generator
        # Only needed for PHP versions prior to 4.2
        mt_srand((double) microtime() * 1000000);

        # Array of characters, adjust as desired
        $chars = array(
            'Q', '@', '8', 'y', '%', '^', '5', 'Z', '(', 'G', '_', 'O', '`',
            'S', '-', 'N', '<', 'D', '{', '}', '[', ']', 'h', ';', 'W', '.',
            '/', '|', ':', '1', 'E', 'L', '4', '&', '6', '7', '#', '9', 'a',
            'A', 'b', 'B', '~', 'C', 'd', '>', 'e', '2', 'f', 'P', 'g', ')',
            '?', 'H', 'i', 'X', 'U', 'J', 'k', 'r', 'l', '3', 't', 'M', 'n',
            '=', 'o', '+', 'p', 'F', 'q', '!', 'K', 'R', 's', 'c', 'm', 'T',
            'v', 'j', 'u', 'V', 'w', ',', 'x', 'I', '$', 'Y', 'z', '*'
        );

        # Array indice friendly number of chars; empty token string
        $numChars = count($chars) - 1;
        $token = '';

        # Create random token at the specified length
        for ($i = 0; $i < $len; $i++)
            $token .= $chars[mt_rand(0, $numChars)];

        # Should token be run through md5?
        if ($md5) {

            # Number of 32 char chunks
            $chunks = ceil(strlen($token) / 32);
            $md5token = '';

            # Run each chunk through md5
            for ($i = 1; $i <= $chunks; $i++)
                $md5token .= md5(substr($token, $i * 32 - 32, 32));

            # Trim the token
            $token = substr($md5token, 0, $len);
        } return $token;
    }

    public function toJSON()
    {
    	return CJSON::encode(array(
    		"_uid"=> $this->_uid,
    		"_oauthToken"=> $this->_oauthToken,
    		"_isAuthen"=> $this->_isAuthen
    	));
    }
}
